package com.raycloud.erp.omll.provider.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.raycloud.secret_api.api.SecretRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Properties;

/**
 * Druid的数据池配置，支持光云的加密和数据库坐标回传机制
 * @author liumingjian
 * @date 2019/1/20
 **/
@Configuration
@ConfigurationProperties(prefix = "spring.datasource.druid")
@Slf4j
public class DruidDataSourceConfiguration {


    static final String PREFIX = "druid";

    String username;

    String password;

    String url;

    String driverClassName;

    Integer maxActive;

    String maxEvictableIdleTimeMillis;

    String maxWait;

    String testOnBorrow;

    String testWhileIdle;

    String validationQuery;

    String poolPreparedStatements;

    String timeBetweenEvictionRunsMillis;

    String minEvictableIdleTimeMillis;

    String filters;

    SecretRequest secretRequest;

    String diamondCoord;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getDriverClassName() {
        return driverClassName;
    }

    public void setDriverClassName(String driverClassName) {
        this.driverClassName = driverClassName;
    }

    public Integer getMaxActive() {
        return maxActive;
    }

    public void setMaxActive(Integer maxActive) {
        this.maxActive = maxActive;
    }

    public String getMaxEvictableIdleTimeMillis() {
        return maxEvictableIdleTimeMillis;
    }

    public void setMaxEvictableIdleTimeMillis(String maxEvictableIdleTimeMillis) {
        this.maxEvictableIdleTimeMillis = maxEvictableIdleTimeMillis;
    }

    public String getMaxWait() {
        return maxWait;
    }

    public void setMaxWait(String maxWait) {
        this.maxWait = maxWait;
    }

    public String getTestOnBorrow() {
        return testOnBorrow;
    }

    public void setTestOnBorrow(String testOnBorrow) {
        this.testOnBorrow = testOnBorrow;
    }

    public String getTestWhileIdle() {
        return testWhileIdle;
    }

    public void setTestWhileIdle(String testWhileIdle) {
        this.testWhileIdle = testWhileIdle;
    }

    public String getValidationQuery() {
        return validationQuery;
    }

    public void setValidationQuery(String validationQuery) {
        this.validationQuery = validationQuery;
    }

    public String getPoolPreparedStatements() {
        return poolPreparedStatements;
    }

    public void setPoolPreparedStatements(String poolPreparedStatements) {
        this.poolPreparedStatements = poolPreparedStatements;
    }

    public String getTimeBetweenEvictionRunsMillis() {
        return timeBetweenEvictionRunsMillis;
    }

    public void setTimeBetweenEvictionRunsMillis(String timeBetweenEvictionRunsMillis) {
        this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
    }

    public String getMinEvictableIdleTimeMillis() {
        return minEvictableIdleTimeMillis;
    }

    public void setMinEvictableIdleTimeMillis(String minEvictableIdleTimeMillis) {
        this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
    }

    public String getFilters() {
        return filters;
    }

    public void setFilters(String filters) {
        this.filters = filters;
    }

    public SecretRequest getSecretRequest() {
        return secretRequest;
    }

    @Autowired(required = false)
    public void setSecretRequest(SecretRequest secretRequest) {
        this.secretRequest = secretRequest;
    }

    public String getDiamondCoord() {
        return diamondCoord;
    }

    public void setDiamondCoord(String diamondCoord) {
        this.diamondCoord = diamondCoord;
    }

    @Bean(initMethod = "init", destroyMethod = "close")
    public DruidDataSource createDataSource(){
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.configFromPropety(buildProperties());
        if(null != secretRequest && StringUtils.isNotEmpty(diamondCoord)){
            dataSource.setPasswordCallback(buildDiamondPasswordCallback());
        }
        return dataSource;
    }

    DiamondPasswordCallback buildDiamondPasswordCallback(){
        DiamondPasswordCallback callback = new DiamondPasswordCallback();
        callback.setSecretRequest(secretRequest);
        callback.setDiamondCoord(diamondCoord);
        log.info("创建了DiamondPasswordCallback，coord:" + diamondCoord);
        return callback;
    }

    Properties buildProperties(){
        DruidPropsWrapper properties = new DruidPropsWrapper();
        properties.putIfNotNull("url", url);
        properties.putIfNotNull("username", username);
        properties.putIfNotNull("password", password);
        properties.putIfNotNull("driverClassName", driverClassName);
        properties.putIfNotNull("maxActive", maxActive);
        properties.putIfNotNull("minEvictableIdleTimeMillis", minEvictableIdleTimeMillis);
        properties.putIfNotNull("maxEvictableIdleTimeMillis", maxEvictableIdleTimeMillis);
        properties.putIfNotNull("validationQuery", validationQuery);
        properties.putIfNotNull("poolPreparedStatements", poolPreparedStatements);
        properties.putIfNotNull("maxWait", maxWait);
        properties.putIfNotNull("testOnBorrow", testOnBorrow);
        properties.putIfNotNull("testWhileIdle", testWhileIdle);
        properties.putIfNotNull("timeBetweenEvictionRunsMillis", timeBetweenEvictionRunsMillis);
        properties.putIfNotNull("filters", filters);
        return properties;
    }

    class DruidPropsWrapper extends Properties {

        public boolean putIfNotNull(String propName, Object propValue){
            if(null == propValue){
                return false;
            }

            put(PREFIX + "." + propName, propValue);
            return true;
        }
    }
}
